#include "test.h"
#include "ui_test.h"
#include <QCryptographicHash>
#include <QTime>
#include <QtGlobal>
#include <rsa.h>
#include <aes.h>
#include <QDir>
#include <QDebug>
#include <string.h>
#include <iostream>
test::test(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::test)
{
    ui->setupUi(this);
}

test::~test()
{
    delete ui;
}

void test::on_pushButton_2_clicked()//开始测试
{
    int i;
    QString s;
    ui->lineEdit->setText("你好你好啊");
    s=ui->lineEdit->text();             //获取明文s
    qDebug()<<"明文s长度:"<<s.length();
    QString md5rslt=MD5encryption(s);   //MD5
    ui->lineEdit_2->setText(md5rslt);

    //rsa签名
    QString rsaplaintext=md5rslt;        //hash值作为RSA明文测试，RSA单次加密最大1024字节
//    rsa t1;                             //RSA加密、解密
    t1.RSA_Initialize();                //先初始化，再将明文/密文 QString->char数组，然后调用加解密函数
    ui->lineEdit_3->setText(QString::number(t1.e));//显示公钥，私钥
    ui->lineEdit_4->setText(QString::number(t1.d));
    QByteArray ba=rsaplaintext.toUtf8();//QString 转字符数组
    char *plain=ba.data();
    int l=rsaplaintext.length();
    for(i=0;i<l;i++){
        t1.plaintext[i]=plain[i];
    }
    t1.Initialize();
    t1.RSA_Signature();
    qDebug()<<"\n 签名完成 \n";
    QString signature=QString::fromLocal8Bit((char*)t1.ciphertext);
    ui->lineEdit_9->setText(signature);//字符数组转QString
    //需要将签名后得到的int数组转为QByteArray,签名使用的字符串格式的

    QString tmp;
    tmp=s+QString::fromLatin1((char*)t1.ciphertext);
    qDebug()<<"签名字符串长度:"<<QString::fromLatin1((char*)t1.ciphertext).length();
    qDebug()<<"原文加签名长度："<<tmp.length();
    ui->lineEdit_5->setText(tmp);//原文加签名处理后就是字符串，然后AES处理后是QByteArray

    //AES加密，包含填充，QString->QByteArray
    QString key1=md5rslt.mid(0,16); //QString 转字符数组,确定AES密钥
    ui->lineEdit_6->setText(key1);
    qDebug()<<key1.length();
    unsigned char* key;
    key=(unsigned char*)qstrdup(key1.toLocal8Bit().data());
    AES aes(key);//一次只能处理16字节数据
    QString plaintext=ui->lineEdit->text()+md5rslt;
    qDebug()<<"the length of plaintext for AES "<<plaintext.length();
    l=plaintext.length();
    //先给输入字符串
    aes.input=plaintext;
    aes.aes_encrypt();//input->output2
    qDebug()<<"AES密文的长度"<<aes.output.length();

    aes.input2=aes.output2;
    aes.aes_decrypt();//input2->output
    ui->lineEdit_7->setText(aes.output);//AES密文

    //要传输的消息是 AES密文+加密后的AES密钥
    //加密用接收方的公钥，现在测试用的是自己的公钥
    rsaplaintext=key1;
    ba=rsaplaintext.toUtf8();//QString 转字符数组
    char *plain2=ba.data();
    l=rsaplaintext.length();
    for(i=0;i<l;i++){
        t1.plaintext[i]=plain2[i];
    }
    t1.Initialize();
    t1.RSA_Encrypt();//加密后的RSA密钥
    t1.RSA_Decrypt();
    ui->rsaaeskey->setText((char*)t1.plaintext);
    QByteArray aeskey;
    for(i=0;i<l;i++){
        aeskey.append(intTo4ByteArray(t1.Ciphertext[i]));
    }
    qDebug()<<"rsa aes key length "<<aeskey.length();
    //ui->rsaaeskey->setText(aeskey);

    rslt=aes.output2+aeskey;
    ui->lineEdit_8->setText(rslt.toBase64());
}

void test::on_pushButton_clicked()  //关闭测试界面
{
    this->hide();
}
QString test::MD5encryption(QString s)
{
    QString rslt;
    rslt=QCryptographicHash::hash(s.toLatin1(),QCryptographicHash::Md5).toHex();
    return rslt;
}
void test::createkey(QString* s1,QString* s2,QString* s3)//密钥生成，生成RSA公钥、私钥、和AES密钥
{
//    qsrand(QTime::currentTime().msec());	//设置种子，该种子作为qrand生成随机数的起始值，RAND_MAX为32767，即随机数在种子值到32767之间
    *s1="";
    *s2="";
    *s3="";
    return;
}


QByteArray test::intTo4ByteArray(int i)
{
    QByteArray ba;
    ba.resize(4);
    ba[0] = (uchar)(0x000000ff & i);
    ba[1] = (uchar)((0x0000ff00&i)>>8);
    ba[2] = (uchar)((0x00ff0000&i)>>16);
    ba[3] = (uchar)((0xff000000&i)>>24);
    return ba;
}
int test::ByteArray4ToInt(const QByteArray &bytes)
{
    int i = bytes[0] & 0x000000FF;
    i |= ((bytes[1] <<8)&0x0000FF00);
    i |= ((bytes[2] <<16)&0x00FF0000);
    i |= ((bytes[3] <<24)&0xFF000000);
    return i;
}

void test::on_pushButton_3_clicked()//解密,先把AES公钥解出来，再解密AES，再验证签名和hash值，设计消息格式时需要在前面标出明文的长度。。。消息格式需要设计
{
//创建rsa 对象，初始化
//交换获得对方rsa的公钥e，n
//由自己rsa私钥解密获得AES密钥
//由AES密钥解密获得AES明文
//提取出明文长度
//进行MD5，签名验证，验证通过后进行处理
}
//设计消息格式：有请求登录信息，用户列表信息，普通信息三种
//请求登录信息包含用户名和密码hash值，和用户ip
//用户列表信息包括用户人数和用户名
//普通信息包括类别，和消息。
